08 Spring Data JPA的@Entity注解 | 您所在的位置:网站首页 › jpa 返回指定列 › 08 Spring Data JPA的@Entity注解 |
Spring Data JPA的@Entity注解
基础注解
@Entity
源码 public @interface Entity { // 可选,默认是此实体类的名字,全局唯一 String name() default ""; }@Entity定义对象将会成为被JPA管理的实体,将映射到指定的数据库表。 @Table用于指定数据库表的表名 源码 package javax.persistence; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface Table { // 表的名字,可选。如果不填写,系统认为和实体的名字一样为表名 String name() default ""; // 此表的catalog,可选 String catalog() default ""; // 此表的schema,可选 String schema() default ""; // 唯一性约束,只有创建表的时候有用,默认不需要 UniqueConstraint[] uniqueConstraints() default {}; //索引,只有创建表的时候使用,默认不需要 Index[] indexes() default {}; } @Id@Id定义属性为数据库的主键,一个实体里面必须有一个 @GeneratedValue源码 @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface GeneratedValue { // Id的生成策略 GenerationType strategy() default GenerationType.AUTO; // 通过Sequence生成Id,常见的是Oracle数据库Id生成规则,需要配合@SequenceGenerator使用 String generator() default ""; }GenerationType一共有四个值 public enum GenerationType { // 通过表产生主键,框架由表模拟序列产生主键,使用该策略可以使应用更易于数据库移植 TABLE, // 通过序列产生主键,通过@SequenceGenerator注解指定序列名称,MySQL不支持这种方式 SEQUENCE, // 采用数据库ID自增长,一般用于MYSQL数据库 IDENTITY, // JPA自动选择合适的策略,是默认选项。 AUTO; private GenerationType() { } } @Basic@Basic表示属性是到数据库表的字段的映射。如果实体的字段没有任何注解,默认即为@Basic @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Basic { // 可选,EAGER为立即加载,LAZY为延迟加载 FetchType fetch() default FetchType.EAGER; // 可选,设置这个字段是否为null,默认为true boolean optional() default true; } @Transient@Transient表示该属性并非一个到数据库表字段的映射,表示持久化属性,与@Basic作用相反。JPA映射数据库的时候就会忽略它。 @Column源码 @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Column { // 数据库中表的列明。可选,默认为与实体属性名保持一样,如果实体属性名中由大写,它会自动分割 String name() default ""; // 是否唯一,默认false,可选 boolean unique() default false; // 数据字段是否允许为空,可选,默认为true boolean nullable() default true; // 执行insert操作的时候是否包含此字段,可选,默认为true boolean insertable() default true; // 执行update的时候是否包含此字段,可选,默认为true boolean updatable() default true; // 表示该字段在数据库中的实际类型 String columnDefinition() default ""; // 数据库字段的长度,可选,默认为255 int length() default 255; } @Temporal@Temporal用来设置Date类型的属性映射到对应精准的字段。 @Temporal(TemporalType.DATA)映射为日期 --data@Temporal(TemporalType.TIME)映射为日期 --time@Temporal(TemporalType.TIMESTAMP)映射为日期 --data time @Enumerated@Enumerated很好用,直接映射enum枚举类型的字段 源码 public @interface Enumerated { // 枚举映射的类型,默认为ORDINAL EnumType value() default EnumType.ORDINAL; }EnumType可选: ORDINAL:映射枚举的下标SIRING:映射枚举的name示例: // 定义一个枚举类 public enum Gender{ MAIL("男性"),FMAIL("女性"); private String value; private Gender(String value){ this.valus = valus; } } //实体类中的使用 @Entity @Table(name = "tb_user") public class User implements Serializable{ @Enumerated(EnumType.STRING) @Column(name = "user_gender") private Gender gender; }这时插入两条数据,数据库里面的值是MAIL/FMAIL,而不是男性、女性,如果是我们用@Enumerated(EnumType.ORDINAL),那么这时数据库里存储的是0,1。但是实际工作中不建议这样做,因为下标使会发生变化。 @LobLob将属性映射为数据库支持的大对象类型,支持以下两种数据库类型的字段 Clob类型是长字符串类型,java.sql.Clob、Character[]、char[]和String将被映射为Clobl类型Blob类型是字节类型,java.sql.Blob、Byte[]、byte[]和实现了Serializable接口的类型将被映射为Blob类型Clob、Blob占用内存空间较大,一般配合@Basic(fatch=FechType.LAZY)将其设置为延迟加载 关联关系注解 @JoinColumn定义外键关联的字段名称 public @interface JoinColumn { // 目标表的字段名,必填 String name() default ""; // 本实体的字段名,非必填,默认为本表ID String referencedColumnName() default ""; // 外键字段是否唯一,默认为false boolean unique() default false; // 外键字段是否允许为空,默认为允许 boolean nullable() default true; // 是否跟随一起新增 boolean insertable() default true; // 是否跟随一起修改 boolean updatable() default true; }用法:主要配合@OneToOne、@ManyToOne、@OneToMany一起使用,但是使用没有意义。 @OneToOne源码 @Target({ElementType.METHOD, ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface OneToOne { // 关系目标实体,非必填,默认为该字段的类型 Class targetEntity() default void.class; // cascade 级联操作策略 // PERSIST 级联新建 // REMOVE 级联删除 // REFRESH 级联刷新 // MERGE 级联更新 // ALL 四项权限 CascadeType[] cascade() default {}; // 数据获取方式,立即加载和延迟加载 FetchType fetch() default FetchType.EAGER; // 是否允许为空 boolean optional() default true; // 关联关系被谁维护,非必填,一般不需要特别指定 String mappedBy() default ""; // 是否级联删除,和CascadeType.REMOVE的效果一样,只要配置了两种的一种就会自动级联删除 boolean orphanRemoval() default false; }用法:@OneToOne需要配合@JoinCloumn一起使用。注意:可以双相关联,也可以只配置一方,需要视需求而定。 示例:假设一个部门只有一个员工 @OneToOne @JoinColumn(name="employee_id",referencedColumnName = "id") private Employee employeeAttribute = new Employee();employee_id指的是Department里面的字段,而referencedColumnName="id"指的是Employee表里面的字段 如果需要双相关联,Employee的内容如下 @OneToOne(mappedBy = "employeeAttribute") private Department department;当然不使用mappedBy,和下面效果是一样的 @OneToOne @JoinColumn(name = "id", referencedColumnName = "employee_id") private Employee employeeAttribute = new Employee(); @OneToMany与@ManyToOne@OneToMany与@ManyToOne可以相对存在,也可以只存在一方 @Entity @Table(name = "user") public class User { @Id private Long id; @OneToMany( cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user" ) private Set setRole; } @Entity @Table(name = "role") public class Role { @Id private Long id; @ManyToOne( cascade = CascadeType.ALL, fetch = FetchType.EAGER ) @JoinColumn(name = "user_id") private User user; } @OrderBy关联查询时排序 public @interface OrderBy { // 要排序的字段,格式如下 // orderby_list::=orderby_item[,orderby_item]* // orderby_item::=[property_or_field_name][ASC|DESC] String value() default ""; }用法 @Entity @Table(name = "user") public class User { @Id private Long id; @OneToMany( cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "user" ) @OrderBy("roleName DESC ") private Set setRole; }OrderBy中的字段对应的是实体中的名称 @JoinTable如果对象与对象之间有一个关联关联表的时候,就会用到@JoinTable,一般和@ManyToMany一起使用。 源码: public @interface JoinTable { // 中间关联关系表名 String name() default ""; // 表的catelog String catalog() default ""; // 表的schema String schema() default ""; // 主链接表的字段 JoinColumn[] joinColumns() default {}; // 被联机的表外键字段 JoinColumn[] inverseJoinColumns() default {}; }示例: 假设Blog和Tag是多对多的关系,有一个关联关系表blog_tag_relation,表中有两个属性blog_id和tag_id,那么Blog实体里面的写法如下: @Entity public class Blog { @Id private Long id; @ManyToMany @JoinTable( name = "blog_tag_relation", joinColumns = @JoinColumn(name = "blog_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "tag_id", referencedColumnName = "id") ) private List tags = new ArrayList(); } @ManyToMany源码 public @interface ManyToMany { Class targetEntity() default void.class; CascadeType[] cascade() default {}; FetchType fetch() default FetchType.LAZY; String mappedBy() default ""; }@ManyToMany表示多对多,和@OneToOne、@ManyToOne一样也有单向、双向之分。单向双向和注解没有关系,只看实体类之间是否相互引用。 示例:一个博客可以有多个标签,一个标签也可以在多个博客上,Blog和Tag就是多对多的关系 // 单向多对多 @Entity public class Blog { @Id private Long id; @ManyToMany @JoinTable( name = "blog_tag_relation", joinColumns = @JoinColumn(name = "blog_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "tag_id", referencedColumnName = "id") ) private List tags = new ArrayList(); } @Entity public class BlogTagRelation { @Column(name = "blog_id") private Integer blogId; @Column(name = "tag_id") private Integer tag_id; } // 双向多对多 @Entity public class Blog { @Id private Long id; @ManyToMany(cascade=CascadeType.ALL) @JoinTable( name = "blog_tag_relation", joinColumns = @JoinColumn(name = "blog_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "tag_id", referencedColumnName = "id") ) private List tags = new ArrayList(); } @Entity public class Tag { @Id private String id; @ManyToMany(mappedBy = "BlogTagRelation") private List blog = new ArrayList(); } @EntityGraphJPA2.1推出的@EnttiyGraph、@NamedEntityGraph用来提高查询效率,很好地解决了N+1条SQL的问题。两者配合起来使用,缺一不可。 1、现在Entity里面定义@NamedEntityGraph,其他不变,其中,@NamedAttributeNode可以有多个,也可以有一个 @NamedEntityGraph( name = "UserInfoEntity.addressEntityList", attributeNodes = { @NamedAttributeNode("addressEntityList"), @NamedAttributeNode("userBlogEntityList") }) @Entity(name = "UserInfoEntity") @Table(name = "user_info", schema = "test") public class UserInfoEntity implements Serializable { @Id @Column(name = "id", nullable = true) private Integer id; @OneToOne(optional = true) @JoinColumn( referencedColumnName = "id", name = "address_id", nullable = false ) private UserReceivingAddressEntity addressEntityList; @OneToMany @JoinColumn(name = "create_user_id", referencedColumnName = "id") private List userBlogEntityList; }2、只需要在查询方法上加@EntityGraph注解即可,其中value就是@NamedEntityGraph中的name。 public interface UserRepository extends JpaRepository { @Override @EntityGraph(value = "UserInfoEntity.addressEntityList") List findAll(); } 关于关系查询的一些坑1、所有的注解要么配置在字段上,要么配置在get方法上,不要混用 2、所有的关联都是支持单向关联和双相关联的。JSON序列化的时候双向注解会产生死循环,需要人为手动转化一次,或者使用@JsonIgnore 3、在所有的关联查询中,表一般是不需要建立外键索引 4、级联删除比较危险,建议考虑清楚,或者完全掌握 5、不同的关联关系的设置,@JoinCloum里面的name、referencedCloumName代表的意思是不一样的,很容易混淆,可以根据打印出来的sql调整 6、当配置这些关联关系的时候建议直接在表上面,把外键建好,然后通过工具生成,这样可以减少调试的时间 |
今日新闻 |
推荐新闻 |
专题文章 |
CopyRight 2018-2019 实验室设备网 版权所有 |